#include "apockernel.h"
#include "apoccommon.h"
#include "apoctextgraphics.h"
#include "apocstring.h"
#include "x86/apocx86.h"

#define DELAY() do { for (Apoc::UInt wait = 0; wait < 0xFFFFFF; ++wait); } while (0);

namespace Apoc
{
  namespace Kernel
  {
    static void Initialize();
    static void RunLoop();
    static void Loop();

    void Main()
    {
      Initialize();

      RunLoop();
    }

    static void Initialize()
    {
      TextGraphics::Clear();
      TextGraphics::SetCursorPosition(0);
      TextGraphics::PutString(GetVersionString().GetData());
      TextGraphics::PutString("\n");

      X86::IDT::Initialize();
      TextGraphics::PutString("IDT ");
      X86::PIC::Initialize();
      TextGraphics::PutString("PIC ");
      X86::PIT::Initialize();
      TextGraphics::PutString("PIT ");
      X86::Keyboard::Initialize();
      TextGraphics::PutString("KEYBRD ");


      UInt c = 0;
      for (;;)
      {
	Int8 buff[0xFF];
        TextGraphics::PutString(IntToDecimalString(c, buff), 1000, TextGraphics::GREEN_FOREGROUND | TextGraphics::INTENSE_FOREGROUND);
	++c;
      }
    }

    static void RunLoop()
    {
      while (true)
	Loop();
    }

    static void Loop()
    {
    }

    UInt GetVersion()
    { return 1; }

    const UTF8Pointer GetVersionString()
    {
      #if APOC_ARCH == APOC_ARCH_X86_32
        static const Int8 apocVersionString[] = "APOC v0.1 x86-32";
      #elif APOC_ARCH == APOC_ARCH_X86_64
        static const Int8 apocVersionString[] = "APOC v0.1 x86-64";
      #endif
      
      return UTF8Pointer(apocVersionString);
    }

    void Log(const UTF8Pointer message)
    {
      TextGraphics::PutString(message.GetData());
    }

    void Halt(const UTF8Pointer reason)
    {
      //TextGraphics::Clear();
      //TextGraphics::SetCursorPosition(0);

      TextGraphics::PutString("SYSTEM FAILURE: ");
      TextGraphics::PutString(reason.GetData());
      
      for (;;);
    }
  }
}
